Skip to content

refactor(attn): let the bucketer define the batched decode kernel's buckets - #792

Closed
jvlunteren wants to merge 2 commits into
torch-spyre:mainfrom
jvlunteren:jvl-bucketer-owns-batched
Closed

refactor(attn): let the bucketer define the batched decode kernel's buckets#792
jvlunteren wants to merge 2 commits into
torch-spyre:mainfrom
jvlunteren:jvl-bucketer-owns-batched

Conversation

@jvlunteren

@jvlunteren jvlunteren commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Description

Makes SpyreAttnBucketer the single source of truth for attention bucket sizes, and has warmup pre-compile the batched decode kernel as well as the per-sequence one. Per review feedback on #772.

The metadata builder computed its own seqs and blocks buckets in parallel with the bucketer computing the same thing, so the set build() dispatched onto and the set warmup recorded agreed only by coincidence. It now reads both from the bucketer. The batched kernel keys on a different tuple from the per-sequence one, so it gets its own bucket type and enumeration, and record_graphs compiles both. Previously the batched kernel compiled lazily in the serving path, the stall warmup exists to prevent. Buckets dispatch cannot reach are pruned.

Rebased onto #789, which routes query and output through fixed-size staging buffers: needs_gather now comes from the sequence counts rather than the query width, which staging made constant, and the recorder records on those buffers instead of fresh tensors.

Stacked on #791, since it uses the new names throughout.

Related Issues

#772 #789 #791

Test Plan

  • pytest tests/runtime/test_spyre_attn_bucketer.py : 69 passed
  • pytest tests/attention/test_spyre_attn.py --attn-shards=4 --attn-shard-id=0 : 46 passed
  • Graph reuse verified on device, with a mismatched control call to confirm the check can fail

Checklist

  • I have read the contributing guidelines
  • My code follows the project's code style (run bash format.sh)
  • I have added tests for my changes (if applicable)
  • I have updated the documentation (if applicable)
  • My commits include a Signed-off-by: line (DCO compliance)

@jvlunteren
jvlunteren requested review from a team and bringlein as code owners September 7, 2026 08:00
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

👋 Hi! Thank you for contributing.
Just a reminder: Make sure that your code passes all the linting checks, otherwise your PR won't be able to be merged. To do so, run ./format.sh.
Now you are good to go 🚀.

We also recommend installing prek and configuring it to check your code before every local commit.

Signed-off-by: Jan van Lunteren <jvl@zurich.ibm.com>
@jvlunteren
jvlunteren force-pushed the jvl-bucketer-owns-batched branch from 2019878 to 620c48d Compare September 7, 2026 13:04
Signed-off-by: Jan van Lunteren <jvl@zurich.ibm.com>
@jvlunteren
jvlunteren force-pushed the jvl-bucketer-owns-batched branch from 620c48d to 5084ae2 Compare September 7, 2026 13:30

@sducouedic sducouedic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look good and clean! just a two small comments

Comment on lines +1532 to +1534
# The buckets are sized from max_model_len; a small KV allocation
# cannot host that many distinct pages to gather.
continue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we print a warning here, or even an assert? I think vllm upstream enforces --num-gpu-blocks-override to serve at least one max-model-len request

Comment on lines +234 to +235
reachable = [n for n in self._num_seqs_buckets if n >= _MIN_BATCHED_SEQS]
for num_seqs in sorted(reachable, reverse=True):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as in the other PR, is there anything preventing us to set _num_seqs_buckets with values already >= _MIN_BATCHED_SEQS

@sducouedic

Copy link
Copy Markdown
Contributor

Superseded by #810.

Most of this has landed independently since the merge-base (0e83fc8): the rename is on main as #791, SPYRE_BATCHED_DECODE is on main, and #799 replaced the per-variant kernel factory with Dynamo-managed compilation — which removes _get_batched_decode_kernel and _decode_fns, the cache batched_variants() was built to mirror. With Dynamo keying on the flags itself, enumerating needs_gather/store_out now traces the same compiled function several times per (num_seqs, num_blocks) pair.

The idea that's still un-done is the one this PR opens with: the bucketer should own the ladders. #810 does that, with you as co-author.

It also fixes a related divergence I hit while extracting it — the builder's num_blocks ladder disagrees with the bucketer's under SPYRE_ATTN_KV_BUCKETS:

default KV buckets:                     both ladders → [1,2,4,8,16,32]   agree
SPYRE_ATTN_KV_BUCKETS=512,1024,2048:    bucketer     → [8,16,32]
                                        old builder  → [1,2,4,8,16,32]   diverge

The builder dispatches onto [1,2,4], which warmup never records — an Inductor compile mid-request, exactly what the recorder exists to prevent. Sharing one ladder makes that unrepresentable.

Leaving this open for you to close, in case you see something in batched_variants() worth keeping.

@jvlunteren jvlunteren closed this Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants